package com.jsjvm.server.dbgproxy.jdwp.cmdsets;

import java.io.IOException;

import com.jsjvm.server.dbgproxy.JDPABackEnd;
import com.jsjvm.server.dbgproxy.JDWPCommandSet;
import com.jsjvm.server.dbgproxy.jdwp.data.JDWPInputStream;
import com.jsjvm.server.dbgproxy.jdwp.data.JDWPOutputStream;
import com.jsjvm.server.dbgproxy.jdwp.data.JDWPRequestHeader;
import com.jsjvm.shared.jdwp.data.JDWPLocation;
import com.jsjvm.shared.vmcmds.VMCommand;

public class JDWPThreadReferenceCommandSet extends JDWPCommandSet{
    // thread reference consants
    private static final int THREAD_NAME_CMD			= 1;
    private static final int THREAD_SUSPEND_CMD			= 2;
    private static final int THREAD_RESUME_CMD			= 3;
    private static final int THREAD_STATUS_CMD			= 4;
    private static final int THREAD_GROUP_CMD			= 5;
    private static final int THREAD_FRAMES_CMD			= 6;
    private static final int THREAD_FRAMES_COUNT_CMD	= 7;
    private static final int OWNED_MONITORS_CMD			= 8;
    private static final int CURRENT_MONITOR_CMD		= 9;
    private static final int THREAD_STOP_CMD			= 10;
    private static final int THREAD_INTERRUPT_CMD		= 11;
    private static final int SUSPEND_COUNT_CMD			= 12;
    private static final int OWNED_STACK_DEPTH_CMD		= 13;
    private static final int FORCE_EARLY_RETURN_CMD		= 14;

    public static final int THREAD_REFERENECE_SET = 11;

	@Override
	public int getCommandSetNumber() {
		return THREAD_REFERENECE_SET;
	}
	
	public JDWPThreadReferenceCommandSet() {
		this.put(THREAD_NAME_CMD, new ThreadName());
		this.put(THREAD_GROUP_CMD, new ThreadGroup());
		this.put(THREAD_STATUS_CMD, new ThreadStatus());
		this.put(THREAD_SUSPEND_CMD, new ThreadSuspend());
		this.put(OWNED_MONITORS_CMD, new OwnedMonitors());
		this.put(CURRENT_MONITOR_CMD, new CurrentContendedMonitors());
		this.put(THREAD_INTERRUPT_CMD, new ThreadInterrupt());
		this.put(SUSPEND_COUNT_CMD, new SuspendCount());
		
		this.put(OWNED_STACK_DEPTH_CMD, JDWPCommandSet.getNIHandler());
		this.put(FORCE_EARLY_RETURN_CMD, JDWPCommandSet.getNIHandler());

		this.put(THREAD_FRAMES_CMD, new ThreadFrames());
	}

	private static class ThreadName extends JDWPCommandHandler {
		@Override
		public VMCommand handleCommand(JDWPRequestHeader hdr, JDWPInputStream is,
				JDWPOutputStream os) throws IOException {
			os.appendString(JDPABackEnd.THREAD_NAME);
			os.commitReplyPacket(hdr);
			return null;
		}
	}

	private static class ThreadGroup extends JDWPCommandHandler {
		@Override
		public VMCommand handleCommand(JDWPRequestHeader hdr, JDWPInputStream is,
				JDWPOutputStream os) throws IOException {
			os.appendInt(JDPABackEnd.THREAD_GROUP_ID);
			os.commitReplyPacket(hdr);
			return null;
		}
	}

	private static class ThreadStatus extends JDWPCommandHandler {
		@SuppressWarnings("unused")
		private static final int ZOMBIE  	= 0;
		private static final int RUNNING 	= 1;
		@SuppressWarnings("unused")
		private static final int SLEEPING	= 2;
		@SuppressWarnings("unused")
		private static final int MONITOR 	= 3;
		@SuppressWarnings("unused")
		private static final int WAIT 		= 4;
		
		private static final int SUSPENDED = 1;
		
		@Override
		public VMCommand handleCommand(JDWPRequestHeader hdr, JDWPInputStream is,
				JDWPOutputStream os) throws IOException {
			os.appendInt(RUNNING);
			os.appendInt(SUSPENDED);
			os.commitReplyPacket(hdr);
			return null;
		}
	}

	// XXX mock implementation
	private static class ThreadFrames extends JDWPCommandHandler {
		@Override
		public VMCommand handleCommand(JDWPRequestHeader hdr, JDWPInputStream is,
				JDWPOutputStream os) throws IOException {
			int tid = is.readID();
			int sframe = is.readInt();
			int lg = is.readInt();
			
			System.out.println("tid " + tid + " sframe " + sframe + " lg " + lg);
	
			os.appendInt(1);
			os.appendInt(3);
			os.appendLocation((byte) 'L', new JDWPLocation(4, 5, 0));
			os.commitReplyPacket(hdr);
			return null;
		}
	}
	// Thread is always suspended when interacts with DBG
	private static class ThreadSuspend extends JDWPCommandHandler {
		@Override
		public VMCommand handleCommand(JDWPRequestHeader hdr, JDWPInputStream is,
				JDWPOutputStream os) throws IOException {
			System.out.println("Thread is always suspended when interacts with DBG");
			os.commitReplyPacket(hdr);
			return null;
		}
	}
	
	// we have no monitor since we are single threaded
	private static class OwnedMonitors extends JDWPCommandHandler {
		@Override
		public VMCommand handleCommand(JDWPRequestHeader hdr, JDWPInputStream is,
				JDWPOutputStream os) throws IOException {
			os.appendInt(0);
			os.commitReplyPacket(hdr);
			return null;
		}
	}

	// we have no monitor since we are single threaded
	private static class CurrentContendedMonitors extends JDWPCommandHandler {
		@Override
		public VMCommand handleCommand(JDWPRequestHeader hdr, JDWPInputStream is,
				JDWPOutputStream os) throws IOException {
			os.appendInt(0);
			os.commitReplyPacket(hdr);
			return null;
		}
	}
	
	// we do nothing since we have no waiting thread
	private static class ThreadInterrupt extends JDWPCommandHandler {
		@Override
		public VMCommand handleCommand(JDWPRequestHeader hdr, JDWPInputStream is,
				JDWPOutputStream os) throws IOException {
			os.commitReplyPacket(hdr);
			return null;
		}
	}
	
	// Thread is always suspended when interacts with DBG
	private static class SuspendCount extends JDWPCommandHandler {
		@Override
		public VMCommand handleCommand(JDWPRequestHeader hdr, JDWPInputStream is,
				JDWPOutputStream os) throws IOException {
			os.appendInt(1);
			os.commitReplyPacket(hdr);
			return null;
		}
	}
}

